import Core.MongoDB as MongoDB
import Core.Gadget as Gadget
import Core.IO as IO
import datetime
import pandas as pd
import numpy as np
from Core.Config import *

# 截面波动率计算函数
def IndentifyMarketDiverge(database):
    #
    bmBarSeries = database.Find("Factor", "DailyReturn", filter={"Symbol": "000001.SH"})

    #
    datetime1 = datetime.datetime(2012, 1, 1)
    datetime2 = datetime.datetime(2013, 1, 1)
    datetime1 = Gadget.ToUTCDateTime(datetime1)
    datetime2 = Gadget.ToUTCDateTime(datetime2)

    #
    filter = {}
    filter["limit"] = 5
    # instruments = database.Find("Instruments", "Stock", filter)
    instruments = Gadget.FindListedInstrument(database, datetime1, datetime2)

    #
    df = IO.LoadMultiInstrumentsFactorsAsDataFrame(database, "DailyReturn", datetime1, datetime2, instruments)
    #print(df)

    symbolsInHeader = df.columns.values
    l = len(df)
    newData = []
    for i in range(l):
        stdDatetime = df["StdDateTime"][i]
        print(i, stdDatetime)

        # ---Exclude New Stock---
        earlyDate = stdDatetime + datetime.timedelta(days=-180)
        listedInstrument = Gadget.FindListedInstrument(database, earlyDate)
        listedSymbols = []
        for instrument in listedInstrument:
            listedSymbols.append(instrument["Symbol"])

        # ---Generate to-deleted List---
        toDeleteSymbols = []
        for symbol in symbolsInHeader:
            if symbol not in listedSymbols:
                toDeleteSymbols.append(symbol)

        # ---Exclude New Stock---
        row = df[i:i+1]
        row = row.drop(columns=toDeleteSymbols)
        # print(row)

        # ---Compute Statistics---
        mean = row.mean(1)[i]
        std = row.std(1)[i]
        print(stdDatetime, mean, std, datetime.datetime.now())
        newData.append([Gadget.ToDateString(stdDatetime), mean, std])
        pass

    dfIndex = pd.DataFrame(newData, columns=["StdDateTime", "Mean", "Std"])
    dfIndex.to_csv("D:/Data/MarketDiverge/" + "MarketDivergeIndex.csv")
    pass


# 截面波动率计算函数
def IndentifyMarketDiverge2(database):

    datetime1 = datetime.datetime(2015, 1, 1)
    datetime2 = datetime.datetime(2019, 4, 4)
    datetime1 = Gadget.ToUTCDateTime(datetime1)
    datetime2 = Gadget.ToUTCDateTime(datetime2)

    # ---load benchmark---
    filter = {}
    filter["StdDateTime"] = {}
    filter["StdDateTime"]["$gte"] = datetime1
    filter["StdDateTime"]["$lte"] = datetime2
    filter["Symbol"] = "000001.SH"
    bmBarSeries = database.Find("Index", "DailyBar", filter)

    # ---loop days---
    newData = []
    for bar in bmBarSeries:
        stdDatetime = bar["StdDateTime"]
        print(stdDatetime)

        # ---Exclude New Stock---
        earlyDate = stdDatetime + datetime.timedelta(days=-180)
        listedInstrument = Gadget.FindListedInstrument(database, earlyDate)
        listedSymbols = []
        for instrument in listedInstrument:
            listedSymbols.append(instrument["Symbol"])

        # ---Find Total "Return Values" at a Specific Day---
        validReturn = []
        # gte = {"Value": {"$gte": -0.11}}
        # lte = {"Value": {"$lte": 0.11}}
        # filter = {"$and": [gte, lte]}
        filter = {}
        filter["StdDateTime"] = stdDatetime
        #
        returns = database.Find("Factor", "DailyReturn", filter)
        for r in returns:
            symbol = r["Symbol"]
            if symbol not in listedSymbols:
                continue
            if r["Value"] > 0.11 or r["Value"] < -0.11:
                continue
            #
            validReturn.append(r["Value"])

        # ---Check Abnormal value---
        #if stdDatetime.month == 2 and stdDatetime.day == 12:
        #    PrintSpecificDayReturn(stdDatetime, returns ,listedSymbols)

        # ---
        mean = np.mean(validReturn)
        std = np.std(validReturn)
        print(stdDatetime, mean, std, len(validReturn), datetime.datetime.now())
        newData.append([Gadget.ToDateString(stdDatetime), mean, std, len(validReturn)])

    #
    dfIndex = pd.DataFrame(newData, columns=["StdDateTime", "Mean", "Std", "Count"])
    dfIndex.to_csv("D:/Data/MarketDiverge/" + "MarketDivergeIndex.csv")
    pass


def PrintSpecificDayReturn(stdDatetime, returns, listedSymbols):
    #
    tempData = []
    for r in returns:
        symbol = r["Symbol"]
        if symbol in listedSymbols:
            tempData.append([symbol, r["Value"]])
    #
    dftemp = pd.DataFrame(tempData, columns=["Symbol", "Value"])
    dftemp.to_csv("D:/Data/MarketDiverge/" + "CheckAbnormal.csv")


def FindAbnormalReturn(database):

    returns = database.Find("Factor", "DailyReturn", filter={"Value": {"$gte": 0.11}})
    #
    for r in returns:
        print(r["Symbol"], r["StdDateTime"], r["Value"])

    #
    returns = database.Find("Factor", "DailyReturn", filter={"Value": {"$lte":-0.11}})
    for r in returns:
        print(r["Symbol"], r["StdDateTime"], r["Value"])


if __name__ == '__main__':

    # ---Connecting Database---
    path_filename = os.getcwd() + "\..\Config\config_local.json"
    database = Config.create_database(database_type="MySQL", config_file=path_filename, config_field="MySQL")
    #
    datetime1 = datetime.datetime(2009, 12, 1)
    datetime2 = datetime.datetime(2021, 1, 1)
    #
    IndentifyMarketDiverge2(database)

    #
    #FindAbnormalReturn(database)